package triIndex;

import transaction.*;
import triDataStruct.*;
import triFileSystem.*;
import triStorage.*;

public class MapManager extends MemoryBuffer implements IMapManager {
	
	private TriMMPFile mmpfile;
	private TriMMPFile inodeFile;
	
	public MapManager(int indexBufferSize, String filename, int pageBufferSize, int pageSize, 
			String inodeFilename, int inodePageBufferSize, int inodePageSize) {
		
		super(indexBufferSize);
		
		mmpfile = new TriMMPFile(filename, pageBufferSize, pageSize);
		if (filename.equals(inodeFilename))
			inodeFile = mmpfile;
		else
			inodeFile = new TriMMPFile(inodeFilename, inodePageBufferSize, inodePageSize);
	}
	
	public void init(Transaction tx) {
		mmpfile.open();
		inodeFile.open();
	}
	
	@Override
	public int createNewMap() {
		return inodeFile.allocNewPage();
	}
	
	@Override
	public void insert(int inodePageId, String key, int value, Transaction tx) {
		int index = this.get(inodePageId, null, tx);
		InsertableMap imap = (InsertableMap)buffer[index];
		imap.insert(key, value, tx);
		this.unPin(index);
	}
	
	public ReadableMap queryMap(int inodePageId, Transaction tx) {
		int index = get(inodePageId, null, tx);
		InsertableMap imap = (InsertableMap)buffer[index];
		PageDir inode = imap.getInodeSnapshot(tx);
		long pos = imap.getFilePos(tx);
		
		//System.out.println("key " + imap.getKey());
		
		unPin(index);
		
		IReader reader = new EndRPageArray(inode, pos, mmpfile);
		ReadableMap qmap = new ReadableMap(reader);
		
		return qmap;
	}
	
	@Override
	public CondQueryIntSet find(int inodePageId, String key, Transaction tx) {
		//Retrieve the qmap
		/*int index = get(inodePageId, null, tx);
		InsertableMap imap = (InsertableMap)buffer[index];
		PageDir inode = imap.getInodeSnapshot(tx);
		long pos = imap.getFilePos(tx);
		
		//System.out.println("key " + imap.getKey());
		
		unPin(index);
		
		IReader reader = new EndRPageArray(inode, pos, mmpfile);
		QueryMap qmap = new QueryMap(reader);*/
		
		
		ReadableMap qmap = this.queryMap(inodePageId, tx);
		
		return new CondQueryIntSet(qmap, key);
	}
	
	@Override
	public void remove(int inodePageId, String key, int value, Transaction tx) {
		//System.out.println(" >>>> remove "+ key + " with " + inodePageId);
		//Retrieve the rmap
		int index = get(inodePageId, null, tx);
		InsertableMap imap = (InsertableMap)buffer[index];
		PageDir inode = imap.getInodeSnapshot(tx);
		long pos = imap.getFilePos(tx);
		unPin(index);
		
		IReader reader = new EndRPageArray(inode, pos, mmpfile);
		IRandIntAccess access = new RandPageAccess(mmpfile);
		RemovableMap rmap = new RemovableMap(reader, access);
		
		rmap.removeItem(key, value, tx);
	}
	
	@Override
	protected BufferObject createEmptyObject(int index, Transaction tx) {
		return new InsertableMap();
	}

	@Override
	protected void loadObject(int inodePageId, Object arg, int index, Transaction tx) {
		//PageDir inode = new PageDir(inodePageId, mmpfile, tx);
		PageDir inode = new PageDir(inodePageId, inodeFile, mmpfile, tx);
		IWriter writer = new WPageArray(inode, mmpfile, tx);
		((InsertableMap)buffer[index]).reset(inodePageId, inode, writer);
	}

	@Override
	protected void flushObject(int index, Transaction tx) {
		// TODO Auto-generated method stub
		
	}
	
	public void dispose(Transaction tx) {
		mmpfile.close();
		if (inodeFile != mmpfile)
			inodeFile.close();
	}
}
